/*
 * Copyright (C) 2014 Realtek Semiconductor Corp.
 * All Rights Reserved.
 *
 * This program is the proprietary software of Realtek Semiconductor
 * Corporation and/or its licensors, and only be used, duplicated,
 * modified or distributed under the authorized license from Realtek.
 *
 * ANY USE OF THE SOFTWARE OTHER THAN AS AUTHORIZED UNDER
 * THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
 *
 * Purpose : Definition of ME handler: Extended ONU-G ZTE (247)
 *
 * Feature : The file includes the following modules and sub-modules
 *           (1) ME handler: Extended ONU-G ZTE (247)
 */

#include "app_basic.h"
#include "feature_mgmt.h"


MIB_TABLE_INFO_T                gMibMe65305TblInfo;
MIB_ATTR_INFO_T                 gMibMe65305AttrInfo[MIB_TABLE_ME65305_ATTR_NUM];
MIB_TABLE_ME65305_T             gMibMe65305DefRow;
MIB_TABLE_OPER_T                gMibMe65305Oper;

static GOS_ERROR_CODE omci_mib_me65305_oper_reset(UINT32 args_num, ...)
{

    MIB_TABLE_ME65305_T       me65305;

    OMCI_LOG(OMCI_LOG_LEVEL_INFO, "Resetting MIB ME 65305");
    MIB_Default(MIB_TABLE_ME65305_INDEX, &me65305, sizeof(MIB_TABLE_ME65305_T));
    me65305.EntityId       = 0x0001;
    GOS_ASSERT(GOS_OK == MIB_Set(MIB_TABLE_ME65305_INDEX, &me65305, sizeof(MIB_TABLE_ME65305_T)));
    OMCI_MeOperCfg(MIB_TABLE_ME65305_INDEX, NULL, &me65305, MIB_ADD,
        omci_GetOltAccAttrSet(MIB_TABLE_ME65305_INDEX, OMCI_ME_ATTR_ACCESS_SBC), OMCI_MSG_BASELINE_PRI_LOW);

    return GOS_OK;
}

GOS_ERROR_CODE me65305_drv_cfg_handler(void              *pOldRow,
                                          void            *pNewRow,
                                          MIB_OPERA_TYPE  operationType,
                                          MIB_ATTRS_SET   attrSet,
                                          UINT32          pri)
{
    MIB_TABLE_ME65305_T *pMe65305 = NULL, *pOldMe65305 = NULL;
    omci_event_msg_t        omciEventMsg;
    UINT32                  strLen;
    FILE                    *fp = NULL;
    
    pMe65305 = pNewRow;
    pOldMe65305 = pOldRow;
    
    switch (operationType)
    {
        case MIB_SET:
        
            if (access("OMCI_PORT80_MODE", 0) < 0)
            {
            // doesn't exist
                if (!(fp = fopen (OMCI_PORT80_MODE, "w")))
                {
                    OMCI_LOG(OMCI_LOG_LEVEL_ERR, "%s():%d fopen %s failed",
                        __FUNCTION__, __LINE__, OMCI_PORT80_MODE);
                    return GOS_FAIL;
                }
                
                fprintf(fp, "Mode=%d\n", pMe65305->Mode);
                fprintf(fp, "Protocol=%d\n", pMe65305->Protocol);
                fprintf(fp, "IngressType=%d\n", pMe65305->IngressType);
                fprintf(fp, "IngressTypeValue=%X\n", pMe65305->IngressTypeValue);
                fprintf(fp, "Start-src-ip="IPADDR_PRINT"\n", IPADDR_PRINT_ARG(pMe65305->StartSrcIP));
                fprintf(fp, "End-src-ip="IPADDR_PRINT"\n", IPADDR_PRINT_ARG(pMe65305->EndSrcIP));
                
                fclose(fp);
            }
            else
            {
                if (MIB_IsInAttrSet(&attrSet, MIB_TABLE_ME65305_MODE_INDEX) &&
                    pMe65305->Mode != pOldMe65305->Mode)
                {
                    CHAR *pStr = NULL;
                    strLen = snprintf(NULL, 0, "=%u", pMe65305->Mode);
                    pStr = (CHAR *)malloc(strLen + 1);
                    snprintf(pStr, strLen + 1, "=%u", pMe65305->Mode);
                    omci_util_conf_replace_opt_val(OMCI_PORT80_MODE, "Mode", pStr);
                    free(pStr);
                }
                if (MIB_IsInAttrSet(&attrSet, MIB_TABLE_ME65305_PROTOCOL_INDEX) &&
                    pMe65305->Protocol != pOldMe65305->Protocol)
                {
                    CHAR *pStr = NULL;
                    strLen = snprintf(NULL, 0, "=%u", pMe65305->Protocol);
                    pStr = (CHAR *)malloc(strLen + 1);
                    snprintf(pStr, strLen + 1, "=%u", pMe65305->Protocol);
                    omci_util_conf_replace_opt_val(OMCI_PORT80_MODE, "Protocol", pStr);
                    free(pStr);
                }
                if (MIB_IsInAttrSet(&attrSet, MIB_TABLE_ME65305_INGRESS_TYPE_INDEX) &&
                    pMe65305->IngressType != pOldMe65305->IngressType)
                {
                    CHAR *pStr = NULL;
                    strLen = snprintf(NULL, 0, "=%u", pMe65305->IngressType);
                    pStr = (CHAR *)malloc(strLen + 1);
                    snprintf(pStr, strLen + 1, "=%u", pMe65305->IngressType);
                    omci_util_conf_replace_opt_val(OMCI_PORT80_MODE, "IngressType", pStr);
                    free(pStr);
                }
                if (MIB_IsInAttrSet(&attrSet, MIB_TABLE_ME65305_INGRESS_TYPE_VALUE_INDEX) &&
                    pMe65305->IngressTypeValue != pOldMe65305->IngressTypeValue)
                {
                    CHAR *pStr = NULL;
                    strLen = snprintf(NULL, 0, "=%X", pMe65305->IngressTypeValue);
                    pStr = (CHAR *)malloc(strLen + 1);
                    snprintf(pStr, strLen + 1, "=%X", pMe65305->IngressTypeValue);
                    omci_util_conf_replace_opt_val(OMCI_PORT80_MODE, "IngressTypeValue", pStr);
                    free(pStr);
                }
                if (MIB_IsInAttrSet(&attrSet, MIB_TABLE_ME65305_START_SRCIP_INDEX) &&
                    pMe65305->StartSrcIP != pOldMe65305->StartSrcIP)
                {
                
                    CHAR *pStr = NULL;
                    strLen = snprintf(NULL, 0, "="IPADDR_PRINT, IPADDR_PRINT_ARG(pMe65305->StartSrcIP));
                    pStr = (CHAR *)malloc(strLen + 1);
                    snprintf(pStr, strLen + 1, "="IPADDR_PRINT, IPADDR_PRINT_ARG(pMe65305->StartSrcIP));
                    omci_util_conf_replace_opt_val(OMCI_PORT80_MODE, "StartSrcIP", pStr);
                    free(pStr);
                }
                if (MIB_IsInAttrSet(&attrSet, MIB_TABLE_ME65305_END_SRCIP_INDEX) &&
                    pMe65305->EndSrcIP != pOldMe65305->EndSrcIP)
                {
                    CHAR *pStr = NULL;
                    strLen = snprintf(NULL, 0, "="IPADDR_PRINT, IPADDR_PRINT_ARG(pMe65305->EndSrcIP));
                    pStr = (CHAR *)malloc(strLen + 1);
                    snprintf(pStr, strLen + 1, "="IPADDR_PRINT, IPADDR_PRINT_ARG(pMe65305->EndSrcIP));
                    omci_util_conf_replace_opt_val(OMCI_PORT80_MODE, "EndSrcIP", pStr);
                    free(pStr);
                }
                
            }
            
            memset(&omciEventMsg, 0, sizeof(omci_event_msg_t));
            omciEventMsg.subType = OMCI_EVENT_TYPE_SET_PORT80_MODE;
            omciEventMsg.status = pMe65305->State;
            
            if (GOS_OK != omci_wrapper_sendOmciEvent(&omciEventMsg))
            {
                OMCI_LOG(OMCI_LOG_LEVEL_ERR, "Send OMCI_EVENT_TYPE_SET_PORT80_MODE fail");
            }
            
            break;

        default:
            break;
    }

    return GOS_OK;
}

GOS_ERROR_CODE mibTable_init(MIB_TABLE_INDEX tableId)
{
    MIB_ATTR_INDEX  attrIndex;    
    UINT8 proprietary_mib_cb_bitmask = 0;
    UINT8 isIgnore = 0;
    if(GOS_OK == omci_ignore_mib_table_check(OMCI_ME_CLASS_ME65305, OMCI_ME_CLASS_SUB_DEFAULT, &isIgnore))
    {
        if(isIgnore)
        {
	        OMCI_PRINT("Ignore classId:%d", OMCI_ME_CLASS_ME65305);
            return GOS_FAIL;
        }

    }

    gMibMe65305TblInfo.Name = "ME65305";
    gMibMe65305TblInfo.ShortName = "ME65305";
    gMibMe65305TblInfo.Desc = "ME65305";
    gMibMe65305TblInfo.ClassId = OMCI_ME_CLASS_ME65305;
    gMibMe65305TblInfo.InitType = OMCI_ME_INIT_TYPE_ONU;
    gMibMe65305TblInfo.StdType = OMCI_ME_TYPE_PROPRIETARY;
    gMibMe65305TblInfo.ActionType = OMCI_ME_ACTION_SET | OMCI_ME_ACTION_GET;
    gMibMe65305TblInfo.pAttributes = &(gMibMe65305AttrInfo[0]);
    gMibMe65305TblInfo.attrNum = MIB_TABLE_ME65305_ATTR_NUM;
    gMibMe65305TblInfo.entrySize = sizeof(MIB_TABLE_ME65305_T);
    gMibMe65305TblInfo.pDefaultRow = &gMibMe65305DefRow;

    attrIndex = MIB_TABLE_ME65305_ENTITY_ID_INDEX - MIB_TABLE_FIRST_INDEX;
    gMibMe65305AttrInfo[attrIndex].Name = "EntityId";
    gMibMe65305AttrInfo[attrIndex].Desc = "Entity ID";
    gMibMe65305AttrInfo[attrIndex].DataType = MIB_ATTR_TYPE_UINT16;
    gMibMe65305AttrInfo[attrIndex].Len = 2;
    gMibMe65305AttrInfo[attrIndex].IsIndex = TRUE;
    gMibMe65305AttrInfo[attrIndex].MibSave = TRUE;
    gMibMe65305AttrInfo[attrIndex].OutStyle = MIB_ATTR_OUT_HEX;
    gMibMe65305AttrInfo[attrIndex].OltAcc = OMCI_ME_ATTR_ACCESS_READ | OMCI_ME_ATTR_ACCESS_SBC;
    gMibMe65305AttrInfo[attrIndex].AvcFlag = FALSE;
    gMibMe65305AttrInfo[attrIndex].OptionType = OMCI_ME_ATTR_TYPE_MANDATORY;

    attrIndex = MIB_TABLE_ME65305_STATE_INDEX - MIB_TABLE_FIRST_INDEX;
    gMibMe65305AttrInfo[attrIndex].Name = "State";
    gMibMe65305AttrInfo[attrIndex].Desc = "State";
    gMibMe65305AttrInfo[attrIndex].DataType = MIB_ATTR_TYPE_UINT8;
    gMibMe65305AttrInfo[attrIndex].Len = 1;
    gMibMe65305AttrInfo[attrIndex].IsIndex = FALSE;
    gMibMe65305AttrInfo[attrIndex].MibSave = TRUE;
    gMibMe65305AttrInfo[attrIndex].OutStyle = MIB_ATTR_OUT_DEC;
    gMibMe65305AttrInfo[attrIndex].OltAcc = OMCI_ME_ATTR_ACCESS_WRITE;
    gMibMe65305AttrInfo[attrIndex].AvcFlag = FALSE;
    gMibMe65305AttrInfo[attrIndex].OptionType = OMCI_ME_ATTR_TYPE_MANDATORY;

    attrIndex = MIB_TABLE_ME65305_MODE_INDEX - MIB_TABLE_FIRST_INDEX;
    gMibMe65305AttrInfo[attrIndex].Name = "Mode";
    gMibMe65305AttrInfo[attrIndex].Desc = "Mode";
    gMibMe65305AttrInfo[attrIndex].DataType = MIB_ATTR_TYPE_UINT8;
    gMibMe65305AttrInfo[attrIndex].Len = 1;
    gMibMe65305AttrInfo[attrIndex].IsIndex = FALSE;
    gMibMe65305AttrInfo[attrIndex].MibSave = TRUE;
    gMibMe65305AttrInfo[attrIndex].OutStyle = MIB_ATTR_OUT_DEC;
    gMibMe65305AttrInfo[attrIndex].OltAcc = OMCI_ME_ATTR_ACCESS_WRITE;
    gMibMe65305AttrInfo[attrIndex].AvcFlag = FALSE;
    gMibMe65305AttrInfo[attrIndex].OptionType = OMCI_ME_ATTR_TYPE_MANDATORY;

    attrIndex = MIB_TABLE_ME65305_PROTOCOL_INDEX - MIB_TABLE_FIRST_INDEX;
    gMibMe65305AttrInfo[attrIndex].Name = "Protocol";
    gMibMe65305AttrInfo[attrIndex].Desc = "Protocol";
    gMibMe65305AttrInfo[attrIndex].DataType = MIB_ATTR_TYPE_UINT8;
    gMibMe65305AttrInfo[attrIndex].Len = 1;
    gMibMe65305AttrInfo[attrIndex].IsIndex = FALSE;
    gMibMe65305AttrInfo[attrIndex].MibSave = TRUE;
    gMibMe65305AttrInfo[attrIndex].OutStyle = MIB_ATTR_OUT_DEC;
    gMibMe65305AttrInfo[attrIndex].OltAcc = OMCI_ME_ATTR_ACCESS_READ;
    gMibMe65305AttrInfo[attrIndex].AvcFlag = FALSE;
    gMibMe65305AttrInfo[attrIndex].OptionType = OMCI_ME_ATTR_TYPE_MANDATORY;

    attrIndex = MIB_TABLE_ME65305_INGRESS_TYPE_INDEX - MIB_TABLE_FIRST_INDEX;
    gMibMe65305AttrInfo[attrIndex].Name = "Ingress Type";
    gMibMe65305AttrInfo[attrIndex].Desc = "Ingress Type";
    gMibMe65305AttrInfo[attrIndex].DataType = MIB_ATTR_TYPE_UINT16;
    gMibMe65305AttrInfo[attrIndex].Len = 2;
    gMibMe65305AttrInfo[attrIndex].IsIndex = FALSE;
    gMibMe65305AttrInfo[attrIndex].MibSave = TRUE;
    gMibMe65305AttrInfo[attrIndex].OutStyle = MIB_ATTR_OUT_DEC;
    gMibMe65305AttrInfo[attrIndex].OltAcc = OMCI_ME_ATTR_ACCESS_WRITE;
    gMibMe65305AttrInfo[attrIndex].AvcFlag = FALSE;
    gMibMe65305AttrInfo[attrIndex].OptionType = OMCI_ME_ATTR_TYPE_MANDATORY;
    
    attrIndex = MIB_TABLE_ME65305_INGRESS_TYPE_VALUE_INDEX - MIB_TABLE_FIRST_INDEX;
    gMibMe65305AttrInfo[attrIndex].Name = "Ingress Type Value";
    gMibMe65305AttrInfo[attrIndex].Desc = "Ingress Type Value";
    gMibMe65305AttrInfo[attrIndex].DataType = MIB_ATTR_TYPE_UINT16;
    gMibMe65305AttrInfo[attrIndex].Len = 2;
    gMibMe65305AttrInfo[attrIndex].IsIndex = FALSE;
    gMibMe65305AttrInfo[attrIndex].MibSave = TRUE;
    gMibMe65305AttrInfo[attrIndex].OutStyle = MIB_ATTR_OUT_HEX;
    gMibMe65305AttrInfo[attrIndex].OltAcc = OMCI_ME_ATTR_ACCESS_WRITE;
    gMibMe65305AttrInfo[attrIndex].AvcFlag = FALSE;
    gMibMe65305AttrInfo[attrIndex].OptionType = OMCI_ME_ATTR_TYPE_MANDATORY;
    
    attrIndex = MIB_TABLE_ME65305_START_SRCIP_INDEX - MIB_TABLE_FIRST_INDEX;
    gMibMe65305AttrInfo[attrIndex].Name = "Start Source IP";
    gMibMe65305AttrInfo[attrIndex].Desc = "Start Source IP";
    gMibMe65305AttrInfo[attrIndex].DataType = MIB_ATTR_TYPE_UINT32;
    gMibMe65305AttrInfo[attrIndex].Len = 4;
    gMibMe65305AttrInfo[attrIndex].IsIndex = FALSE;
    gMibMe65305AttrInfo[attrIndex].MibSave = TRUE;
    gMibMe65305AttrInfo[attrIndex].OutStyle = MIB_ATTR_OUT_HEX;
    gMibMe65305AttrInfo[attrIndex].OltAcc = OMCI_ME_ATTR_ACCESS_WRITE;
    gMibMe65305AttrInfo[attrIndex].AvcFlag = FALSE;
    gMibMe65305AttrInfo[attrIndex].OptionType = OMCI_ME_ATTR_TYPE_MANDATORY;

    attrIndex = MIB_TABLE_ME65305_END_SRCIP_INDEX - MIB_TABLE_FIRST_INDEX;
    gMibMe65305AttrInfo[attrIndex].Name = "End Source IP";
    gMibMe65305AttrInfo[attrIndex].Desc = "End Source IP";
    gMibMe65305AttrInfo[attrIndex].DataType = MIB_ATTR_TYPE_UINT32;
    gMibMe65305AttrInfo[attrIndex].Len = 4;
    gMibMe65305AttrInfo[attrIndex].IsIndex = FALSE;
    gMibMe65305AttrInfo[attrIndex].MibSave = TRUE;
    gMibMe65305AttrInfo[attrIndex].OutStyle = MIB_ATTR_OUT_HEX;
    gMibMe65305AttrInfo[attrIndex].OltAcc = OMCI_ME_ATTR_ACCESS_WRITE;
    gMibMe65305AttrInfo[attrIndex].AvcFlag = FALSE;
    gMibMe65305AttrInfo[attrIndex].OptionType = OMCI_ME_ATTR_TYPE_MANDATORY;


    memset(&gMibMe65305DefRow, 0x00, sizeof(gMibMe65305DefRow));
    gMibMe65305DefRow.Mode = 1;
    gMibMe65305DefRow.Protocol= 1;
    gMibMe65305DefRow.IngressType = 511;
    gMibMe65305DefRow.IngressTypeValue = 0xff;
    
    
    memset(&gMibMe65305Oper, 0x0, sizeof(MIB_TABLE_OPER_T));
    gMibMe65305Oper.meOperDrvCfg = me65305_drv_cfg_handler;
    gMibMe65305Oper.meOperConnCfg = NULL;
    gMibMe65305Oper.meOperConnCheck = NULL;
    gMibMe65305Oper.meOperDump = omci_mib_oper_dump_default_handler;
    gMibMe65305Oper.meOperCb[PROPRIETARY_MIB_CB_RESET] = omci_mib_me65305_oper_reset;

    MIB_TABLE_ME65305_INDEX = tableId;
    MIB_InfoRegister(tableId, &gMibMe65305TblInfo, &gMibMe65305Oper);
    
    proprietary_mib_cb_bitmask = (1 << PROPRIETARY_MIB_CB_RESET);
    MIB_Proprietary_Reg(tableId, proprietary_mib_cb_bitmask);

    return GOS_OK;
}
